/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ill_be_bach;

import ill_be_bach.model.Beat;
import ill_be_bach.model.Accidental;
import ill_be_bach.model.Chord;
import ill_be_bach.model.Tempo;
import ill_be_bach.model.Note;
import ill_be_bach.model.Key;
import ill_be_bach.model.KeySignature;
import ill_be_bach.model.Song;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.Timer;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

/**
 *
 * @author Abhi
 */
public class MainController {

    private Song song = new Song() ;
    private Chord currentChord = null ;
    SongPlayer songPlayer = new SongPlayer() ;
    Timer recorderTimer = new Timer() ;

    private final int NUM_KEYS = 50 ;

    public void play(int voice, boolean chordMode, Key key, Accidental accidental, Beat beat, int octave, boolean saveToSong) {
        Note note = new Note(key, accidental, octave);
        if (!chordMode || currentChord == null) {
            currentChord = new Chord(note, beat);
            if (saveToSong)
                song.addChord(currentChord, voice);
        }
        else {
            currentChord.notes.add(note);
        }
        songPlayer.play(currentChord, song.getKeySignature()) ;
        if (!chordMode)
            currentChord = null ;
    }

    public Song getSong() {
        return song ;
    }

    public void play() {
        songPlayer.play(song) ;
    }

    public void pause() {
        songPlayer.pause();
    }

    public void stopPlay() {
        songPlayer.stop();
    }

    public void clear() {
        song.clear() ;
    }

    public void remove(int voice) {
        song.removeChord(voice) ;
    }

    public void forward(int voice) {
        song.forward(voice);
    }

    public void rewind(int voice) {
        song.rewind(voice);
    }

    public void record() {
        recorderTimer = new Timer() ;
        double eighthBeatPeriod = 60.0/(song.getTempo().getBeatsPerMinute() * 2) ;
        recorderTimer.schedule(new RecorderTask(song), 0, (int)(eighthBeatPeriod * 1000));
    }

    public void stopRecord() {
        recorderTimer.cancel();
    }

    public boolean load(File file) {
        if (file.getName().endsWith(".midi")) {
            Song loadedSong = songPlayer.loadMidi(file);
            if (loadedSong == null)
                return false ;
            song = loadedSong ;
            return true ;
        }
        else if (file.getName().endsWith(".illbebach")) {
           FileInputStream fis = null;
           ObjectInputStream in = null;
           try
           {
             fis = new FileInputStream(file.getPath());
             in = new ObjectInputStream(fis);
             song = (Song)in.readObject();
             in.close();
             return true ;
           }
           catch(IOException ex)
           {
               return false ;
           }
           catch(ClassNotFoundException ex)
           {
               return false ;
           }
        } else
           return false ;
    }

    public boolean save(File file, JPanel panel) {
        String filename = file.getName();
        if (filename.matches("([^\\s]+(\\.(?i)(jpg|png|gif|bmp))$)")) {
            try {
                int w = panel.getWidth();
                int h = panel.getHeight();
                BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                Graphics2D g = bi.createGraphics();
                panel.paint(g);
                ImageIO.write(bi,"gif",file);
                return true ;
            } catch (Exception ex){
                return false ;
            }
        }
        else if(filename.endsWith(".midi")) {
            return songPlayer.saveAsMidi(song, file);
        }
        else if (filename.endsWith(".illbebach")) {
            FileOutputStream fos = null;
            ObjectOutputStream out = null;
            try
            {
                fos = new FileOutputStream(file.getPath());
                out = new ObjectOutputStream(fos);
                out.writeObject(song);
                out.close();
                return true ;
             }
             catch(IOException ex)
             {
                 return false ;
             }
        } else
            return false ;
    }

    public void setSongProperties(String title, Tempo tempo, ArrayList<Integer> trebleVoices,
            ArrayList<Integer> bassVoices, KeySignature keySignature) {

        song.setSongProperties(title, tempo, trebleVoices, bassVoices, keySignature);
    }

    public int getNumKeys() {
        return NUM_KEYS ;
    }
}
